#include <iostream>
#include <string>
#include <memory>
#include <unordered_map>

#include "Connection.hpp"
#include "Epoller.hpp"
#include "InetAddr.hpp"

class Reactor
{
    const static int gnum = 128;

public:
    Reactor() : _epoller(std::make_unique<Epoller>())
    {
    }

    void AddConnection(int fd, uint32_t events, const InetAddr &addr, int type)
    {
        // 1. 构建connection
        Connection *conn = new Connection(fd);
        conn->SetEvents(events);
        conn->SetReactor(this);
        conn->SetAddr(addr);
        conn->SetConnectionType(type);
        if (conn->Type() == ListenConnection)
        {
            conn->RegisterHandler(_OnConnect, nullptr, nullptr);
        }
        else
        {
            conn->RegisterHandler(_OnRecver, _OnSender, _OnExcepter);
        }

        // 2. fd和关心的事件写透到内核，托管给内核
        if (!_epoller->AddEvents(fd, events))
            return;
        // 3. 托管给connections
        _connections.emplace(fd, conn);
    }
    void EnableConnectionReadWrite(int sockfd, bool readable, bool writeable)
    {
        if (!IsConnectionExits(sockfd))
        {
            return;
        }
        uint32_t events = (readable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0) | (EPOLLET);
        _connections[sockfd]->SetEvents(events);
        _epoller->ModEvents(_connections[sockfd]->Sockfd(),_connections[sockfd]->Events());
    }

    void PrinDebug()
    {
        std::string fdlist;
        for (auto conn : _connections)
        {
            fdlist += std::to_string(conn.second->Sockfd()) + " ";
        }
        LOG(DEBUG, "epoll 管理的fd列表: %s\n", fdlist.c_str());
    }

    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(revs, gnum, timeout);
        for (int i = 0; i < n; ++i)
        {
            int sockfd = revs[i].data.fd;
            uint32_t revents = revs[i].events;
            if (revents | EPOLLHUP)
                revents |= EPOLLIN | EPOLLOUT;
            if (revents | EPOLLERR)
                revents |= EPOLLIN | EPOLLOUT;
            if (revents | EPOLLIN)
            {
                if (IsConnectionExits(sockfd) && _connections[sockfd]->_handler_recver)
                {
                    _connections[sockfd]->_handler_recver(_connections[sockfd]);
                }
            }
            if (revents | EPOLLOUT)
            {
                if (IsConnectionExits(sockfd) && _connections[sockfd]->_handler_sender)
                {
                    _connections[sockfd]->_handler_sender(_connections[sockfd]);
                }
            }
        }
    }
    void DelConnection(int sockfd)
    {
        if(!IsConnectionExits(sockfd))
            return ;
        LOG(INFO,"sockfd %d quit,服务器释放所有资源",sockfd);
        //1. 内核移除sockfd关心
        EnableConnectionReadWrite(sockfd,false,false);
        _epoller->DelEvent(sockfd);

        //2. sockfd关闭
        if(IsConnectionExits(sockfd))
            _connections[sockfd]->Close();

        //3. reactor移除对connection关心
        delete _connections[sockfd];
        _connections.erase(sockfd);
    }
    void Dispatcher()
    {
        _isrunning = true;
        int timeout = -1;
        while (_isrunning)
        {
            LoopOnce(timeout);
            PrinDebug();
        }
        _isrunning = false;
    }
    bool IsConnectionExits(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }
    void SetOnConnect(hander_t OnConnect)
    {
        _OnConnect = OnConnect;
    }
    void SetHandler(hander_t OnRecver, hander_t OnSender, hander_t OnExcepter)
    {
        _OnRecver = OnRecver;
        _OnSender = OnSender;
        _OnExcepter = OnExcepter;
    }
    ~Reactor()
    {
    }

private:
    // key : sockfd
    // val : Connection*
    std::unordered_map<int, Connection *> _connections;
    std::unique_ptr<Epoller> _epoller;
    bool _isrunning = false;
    struct epoll_event revs[gnum];

    // 获取新连接
    hander_t _OnConnect;
    // IO处理
    hander_t _OnRecver;
    hander_t _OnSender;
    hander_t _OnExcepter;
};